#nullable enable

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using PHMEE.PHM.Algorithms.Diagnosis;
using Volo.Abp.Domain.Services;

namespace PHMEE.Managers.Diagnosis;

/// <summary>
/// 柴油发电机故障诊断
/// </summary>
public class DieselGeneratorFaultDiagnosisDomainService : DomainService, IDieselGeneratorFaultDiagnosisDomainService
{
    private readonly DieselGeneratorAlg _dieselGeneratorAlg;

    public DieselGeneratorFaultDiagnosisDomainService(
        DieselGeneratorAlg dieselGeneratorAlg)
    {
        _dieselGeneratorAlg = dieselGeneratorAlg;
    }

    /// <summary>
    /// 柴油发电机故障诊断
    /// </summary>
    /// <param name="pointPosition"></param>
    /// <param name="sampleRate"></param>
    /// <param name="unitWithEquips"></param>
    /// <param name="data"></param>
    /// <exception cref="ArgumentNullException"></exception>
    /// <returns></returns>
    public async Task<string[]> FaultDiagnosisAsync(PointPosition pointPosition, float sampleRate,
        UnitWithEquipsDto unitWithEquips,
        float[] data)
    {
        // 设备参数和阈值初始化
        var equipmentParameters = new DieselGeneratorEquipmentParameters();
        var thresholds = new DieselGeneratorThresholds();

        // 验证并提取设备信息
        var (dieselEngine, generator) = ValidateAndExtractUnitEquipments(unitWithEquips.UnitEquips);

        // 提取柴油机参数
        ExtractDieselEngineParameters(dieselEngine, equipmentParameters);

        // 提取发电机参数
        ExtractGeneratorParameters(generator, equipmentParameters);

        // 提取阈值
        ExtractThresholds(unitWithEquips.Unit, thresholds);

        // 调用柴油发电机算法
        var response = await _dieselGeneratorAlg.DieselGeneratorAsync(pointPosition, data, sampleRate,
            equipmentParameters, thresholds);

        return response.FaultCodes.ToArray();
    }

    private static (MainGeneratorDiesel, MainGenerator) ValidateAndExtractUnitEquipments(List<Equipment> unitEquips)
    {
        if (unitEquips.Count == 0)
        {
            throw new InvalidOperationException(nameof(Equipment));
        }

        if ((unitEquips.FirstOrDefault(e => e.Type == EquipmentEnum.MainGeneratorDiesel)
             ?? throw new InvalidOperationException(nameof(EquipmentEnum.MainGeneratorDiesel)))
            is not MainGeneratorDiesel mainGeneratorDieselEquip)
        {
            throw new InvalidOperationException(nameof(MainGeneratorDiesel));
        }

        mainGeneratorDieselEquip.DeserializeProperties();

        if ((unitEquips.FirstOrDefault(e => e.Type == EquipmentEnum.MainGenerator)
             ?? throw new InvalidOperationException(nameof(EquipmentEnum.MainGenerator)))
            is not MainGenerator mainGeneratorEquip)
        {
            throw new InvalidOperationException(nameof(MainGenerator));
        }

        mainGeneratorEquip.DeserializeProperties();

        return (mainGeneratorDieselEquip, mainGeneratorEquip);
    }

    private static void ExtractDieselEngineParameters(MainGeneratorDiesel dieselEngine,
        DieselGeneratorEquipmentParameters equipmentParameters)
    {
        if(dieselEngine.RatedSpeed is null)
        {
            throw new Exception("额定转速为null");
        }
        equipmentParameters.Rpm = (float)dieselEngine.RatedSpeed;
        equipmentParameters.Power = (float)dieselEngine.PowerCylinderPer;
        equipmentParameters.Cylinders = (float)dieselEngine.CylinderNumber;
    }

    private static void ExtractGeneratorParameters(MainGenerator generator,
        DieselGeneratorEquipmentParameters equipmentParameters)
    {
        equipmentParameters.Lf = (float)generator.Frequency;
    }

    /// <summary>
    /// 从 Unit 提取阈值
    /// </summary>
    /// <param name="unit"></param>
    /// <param name="thresholds"></param>
    private static void ExtractThresholds(Unit unit, DieselGeneratorThresholds thresholds)
    {
        if (unit is MainGeneratorUnit mainGeneratorUnit)
        {
            ExtractThresholdsForMainGenerator(mainGeneratorUnit, thresholds);
        }
        else
        {
            throw new InvalidOperationException(nameof(Unit));
        }
    }
    
    /// <summary>
    /// 主发电机机组阈值提取
    /// </summary>
    /// <param name="unit"></param>
    /// <param name="thresholds"></param>
    private static void ExtractThresholdsForMainGenerator(MainGeneratorUnit unit, DieselGeneratorThresholds thresholds)
    {
        unit.DeserializeProperties();

        thresholds.Acc = (float)unit.Acc;
        thresholds.QzAccRms = (float)unit.QZAccRms;
        thresholds.QgAccRms = (float)unit.QGAccRms;
        thresholds.ZwAccRms = (float)unit.ZWAccRms;
        thresholds.DRms = (float)unit.DRms;
        thresholds.GRms.AddRange(new[] { (float)unit.GRmsA, (float)unit.GRmsB, (float)unit.GRmsC });
        thresholds.GBushBear.AddRange(new[] { (float)unit.GBushBearA, (float)unit.GBushBearB, (float)unit.GBushBearC, (float)unit.GBushBearD, (float)unit.GBushBearE, (float)unit.GBushBearF });
        thresholds.ResonanceFault = (float)unit.ResonanceFault;
        thresholds.StructureLoose = (float)unit.StructureLoose;
        thresholds.CouplingMisalignment.AddRange(new[] { (float)unit.CouplingMisalignmentA, (float)unit.CouplingMisalignmentB });
        thresholds.ValueIgnition = (float)unit.ValueLgnition;
        thresholds.Value1X.AddRange(new[] { (float)unit.Value1XA, (float)unit.Value1XB });
        thresholds.ArmatureFault = (float)unit.ArmatureFault;
        thresholds.DBushBear.AddRange(new[] { (float)unit.DBushBearA, (float)unit.DBushBearB, (float)unit.DBushBearC, (float)unit.DBushBearD, (float)unit.DBushBearE, (float)unit.DBushBearF });
        thresholds.ZjWearFault.AddRange(new[] { (float)unit.ZJWearFaultA, (float)unit.ZJWearFaultB, (float)unit.ZJWearFaultC, (float)unit.ZJWearFaultD, (float)unit.ZJWearFaultE, (float)unit.ZJWearFaultF });
        thresholds.QgWearFault.AddRange(new[] { (float)unit.QGWearFaultA, (float)unit.QGWearFaultB, (float)unit.QGWearFaultC, (float)unit.QGWearFaultD, (float)unit.QGWearFaultE, (float)unit.QGWearFaultF });
    }
}